﻿#include "calibration.h"
#include "halconcpp/HalconCpp.h"
#include "qdebug.h"
#include <QDir>
using namespace HalconCpp;
calibration::calibration()
{

}

bool calibration::Read_Txt(int index)
{

    Num_Txt=0;
    QFile file;
    QString CalPath1= QDir::currentPath()+"/Cal/Cal_Cricle/Cricle.txt";
    QString CalPath2= QDir::currentPath()+"/Cal/Cal_Length/Length.txt";

    switch (index) {
    case 1:
        file.setFileName(CalPath1);
        break;
    case 2:
        file.setFileName(CalPath2);
        break;
    default:
        break;

    }
    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        while(!file.atEnd())
        {
            QByteArray line = file.readLine();
            QString str(line);
            if(str.toFloat()!=0)
            {
                Real_Size[Num_Txt]=str.toFloat();
                Num_Txt++;
            }
        }
        return true;
    }
    else
    {
        return false;
    }
    file.close();
}


//玻璃的坐标基本固定不变，就是被测物上表面的高度随着被测物的长度变化而变化
bool calibration::Cal_Length(float x,float y,float &scale)
{
    HObject ROI,img;
    HObject ImageReduced, Region;
    HTuple  Index, Area, Row, Column;
    HTuple  Height, Row1, Row2, Column1, Column2;
    HTuple  Row11, Row21, Column11, Column21, MetrologyHandle1;
    HTuple  line1, MetrologyHandle2 ;
    HTuple  line2, Distance;
    HTuple  hv_ImageFiles;
    float Total=0;
    float Mes_Length=80;
    HObject ho_ROI_0,ho_ImageReduced,ho_Region,ho_RegionTrans;
    HTuple hv_Row1, hv_Column1, hv_Row2,hv_Column2;
    //确定玻璃边缘得坐标


    QString Img_Path= QDir::currentPath()+"/Cal/Cal_Length/Pic";
    try
    {
        ListFiles(Img_Path.toLatin1().data(), (HTuple("files").Append("follow_links")),
                  &hv_ImageFiles);
        TupleRegexpSelect(hv_ImageFiles, (HTuple("\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$").Append("ignore_case")),
                          &hv_ImageFiles);
        if((hv_ImageFiles.TupleLength()<=20)&&(hv_ImageFiles.TupleLength()>=5)&&(hv_ImageFiles.TupleLength().D()==Num_Txt))
        {
            for(int i=0;i<hv_ImageFiles.TupleLength();i++)
            {
                ReadImage(&img, HTuple(hv_ImageFiles[i]));
                //定位玻璃边
                GenRectangle1(&ho_ROI_0, 1659.96, 1421.59, 1832.63, 1782.53);
                ReduceDomain(img, ho_ROI_0, &ho_ImageReduced);
                Threshold(ho_ImageReduced, &ho_Region, 128, 255);
                ShapeTrans(ho_Region, &ho_RegionTrans, "rectangle1");
                SmallestRectangle1(ho_RegionTrans, &hv_Row1, &hv_Column1, &hv_Row2, &hv_Column2);

                //


                GenRectangle2(&ROI,(HTuple)x, (HTuple)y, 0, 900, 200);
                ReduceDomain(img, ROI, &ImageReduced);
                Threshold(ImageReduced, &Region, 0, 128);
                AreaCenter(Region, &Area, &Row, &Column);
                Connection (Region, &Region);
                SelectShape (Region, &Region, "area", "and", 10000, 99999000000);

                RegionFeatures(Region, "height", &Height);
                Row = Row-(Height/2);
                Row1 = Row-15;
                Row2 = Row-15;
                Column1 = Column-Mes_Length;
                Column2 = Column+Mes_Length;
                Row11 = hv_Row1;
                Row21 = hv_Row1;
                //                Row11 = x;
                //                Row21 = x;
                //                Column11 = y-Mes_Length;
                //                Column21 = y+Mes_Length;
                Column11 = 1550-Mes_Length;
                Column21 = 1550+Mes_Length;
                //上半部分
                CreateMetrologyModel(&MetrologyHandle1);
                AddMetrologyObjectLineMeasure(MetrologyHandle1, Row1, Column1, Row2,
                                              Column2, 20, 5, 1, 30, HTuple(), HTuple(), &Index);
                ApplyMetrologyModel(ImageReduced, MetrologyHandle1);
                GetMetrologyObjectResult(MetrologyHandle1, "all", "all", "result_type", "all_param",
                                         &line1);

                //下半部分
                CreateMetrologyModel(&MetrologyHandle2);
                AddMetrologyObjectLineMeasure(MetrologyHandle2, Row11, Column11, Row21,
                                              Column21, 20, 5, 1, 30, HTuple(), HTuple(), &Index);
                ApplyMetrologyModel(ImageReduced, MetrologyHandle2);
                GetMetrologyObjectResult(MetrologyHandle2, "all", "all", "result_type", "all_param",
                                         &line2);
                if(line1.D()!=0&&line2.D()!=0)
                {
                    Distance=(line2[0]+line2[2])/2-(line1[0]+line1[2])/2;
                    Total+=(float)(Real_Size[i]/Distance);
                }
                else
                {
                    return false;
                }
            }
            scale=Total/hv_ImageFiles.TupleLength();
            return true;
        }
        else
        {
            return false;
        }

    }

    catch(HException &exception)
    {
        return false;
    }
}


bool calibration::Cal_Cricle(float &scale)
{
    float Total=0;
    HObject Img,ROI_Img,ROI;
    HObject Region,Contour;
    HTuple Num,Area,Row,Column,Radius;
    HTuple Value,Para,MetrologyHandle,Index;
    HTuple hv_ImageFiles,Parameter,Phi,Length1,Length2,StartPhi,EndPhi,PointOrder;
    QString Img_Path= QDir::currentPath()+"/Cal/Cal_Cricle/Pic";
    try
    {
        ListFiles(Img_Path.toLatin1().data(), (HTuple("files").Append("follow_links")),
                  &hv_ImageFiles);
        TupleRegexpSelect(hv_ImageFiles, (HTuple("\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$").Append("ignore_case")),
                          &hv_ImageFiles);
        if((hv_ImageFiles.TupleLength()>=5)&&(hv_ImageFiles.TupleLength().D()==Num_Txt))
        {
            for(int i=0;i<hv_ImageFiles.TupleLength();i++)
            {
                ReadImage(&Img, HTuple(hv_ImageFiles[i]));
                GenRectangle1(&ROI, 665.421, 796.379, 1425.03, 1732.4);
                ReduceDomain(Img, ROI, &ROI_Img);

                Threshold(ROI_Img, &Region, 0, 128);
                Connection (Region, &Region);
                SelectShape(Region, &Region, (HTuple("area").Append("convexity")),
                            "and", (HTuple(140000).Append(0.8)), (HTuple(500000).Append(1)));
                CountObj(Region,&Num);
                if(Num.D()==1)
                {
                    AreaCenter(Region, &Area, &Row, &Column);
                    RegionFeatures (Region, "width", &Value);
                    Radius = Value/2;
                    Para.Clear();
                    Para.Append(Row).Append(Column).Append(0).Append(Radius).Append(Radius);

                    CreateMetrologyModel(&MetrologyHandle);
                    AddMetrologyObjectGeneric(MetrologyHandle, "ellipse", Para, 70, 5,
                                              1, 30, HTuple(), HTuple(), &Index);
                    ApplyMetrologyModel(ROI_Img, MetrologyHandle);

                    GetMetrologyObjectResult(MetrologyHandle, "all", "all", "result_type",
                                             "all_param", &Parameter);
                    GetMetrologyObjectResultContour(&Contour, MetrologyHandle, "all",
                                                    "all", 1.5);
                    FitEllipseContourXld(Contour, "ftukey", -1, 2, 0, 200, 3, 2, &Row, &Column,
                                         &Phi, &Length1, &Length2, &StartPhi, &EndPhi, &PointOrder);
                    Total += (float)(Real_Size[i]/((Length1+Length2)/2));
                }
                else
                {
                    return false;
                }
            }
            scale=Total/hv_ImageFiles.TupleLength();
            return true;
        }
        else
        {
            return false;
        }
    }
    catch(HException &exception)
    {
        return false;
    }
}


bool calibration::Cal(int index,int x,int y,float &scale)
{
    switch (index) {
    case 1:
        Flag_R=Read_Txt(1);
        Flag_C=Cal_Cricle(scale);

        break;
    case 2:
        Flag_R=Read_Txt(2);
        Flag_C=Cal_Length(x,y,scale);
        break;
    default:
        break;
    }
    Num_Txt=0;
    Flag=(Flag_R&&Flag_C);

    return Flag;
}
